package NG::Chat::Message;
use strict;
use warnings;
use utf8;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(
SockMessage
SockParse
HttpMessage
HttpParse
);

use HTTP::Parser::XS qw(parse_http_request);
use HTTP::Status;
use JSON::XS;
use NG::Sys::Datetime;
#use NG::Chat::Util;


sub SockMessage {
	my $msg = shift;
	my $status = delete $msg->{status} || 200;
	#$msg->{ts} ||= unixtime2hms();
	$msg->{rid} ||= -1;
	$msg->{type} ||= "response";
	return encode_json($msg).chr(0);
}
sub SockParse {
	my $ref_str = shift;
	if(length($$ref_str) > 4096){
		return {error=>501,text=>"too long"};
	}
	my $i = index($$ref_str,chr(0));
	if($i == -1){
		return 0;
	}
	my $str = substr($$ref_str,0,$i+1,"");
	my $msg;
	local $SIG{__DIE__};
	eval {
		$msg = decode_json($str);
	};
	if($@){
		return {error=>503,text => $@};
	}
	return $msg;
}
sub HttpParse {
	my $ref_str = shift;
	my $len_msg;
	if(($len_msg = length($$ref_str)) > 4096){
		return {error=>501,text=>"too long"};
	}
	my $param = {};
	my $header_size = parse_http_request($$ref_str,$param);
	if($header_size == -2){
		# неполное сообщение
		return undef;
	}elsif($header_size == -1){
		# поломанное сообщение
		return {error=>502,text=>"broken message"};
	}
	if($param->{CONTENT_LENGTH} && $param->{CONTENT_LENGTH} + $header_size > $len_msg){
		# неполное сообщение
		return undef;
	}
	unless($param->{CONTENT_LENGTH}){
		$param->{CONTENT_LENGTH} = $len_msg - $header_size;
	}
	my $body_len = $len_msg - $header_size;
	my $body = substr($$ref_str,$header_size,$body_len);

	substr($$ref_str,0,$len_msg,"");
	
	my $msg;
	local $SIG{__DIE__};
	eval {
		$msg = decode_json($body);
	};
	if($@){
		return {error=>503,text => $@};
	}
	($msg->{cmd} = $param->{PATH_INFO}) =~ s|.*/||;
	$msg->{header} = $param;
	return $msg;
}
sub HttpMessage {
	my $msg = shift;
	my $status = delete $msg->{status} || 200;
	#$msg->{ts} ||= unixtime2hms();
	$msg->{rid} ||= -1;
	$msg->{type} ||= "response";
	my $body = encode_json($msg);
	my $ret =
		"HTTP/1.1 ".$status." ".HTTP::Status::status_message($status)."\n"
		."Content-Length: ".length($body)."\n"
		."Content-Type: text/x-javascript\n"
		."Connection: close\n"
		."\n"
		.$body;
	return $ret;
}


1;
